/*  This file is part of CASpp.

    CASpp is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    CASpp is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with CASpp.  If not, see <http://www.gnu.org/licenses/>.

    Copyright 2014 Jérome LAURENS

    See https://code.google.com/p/idalgo/

*/

#ifndef CASPP_COMPARE_H
#define CASPP_COMPARE_H

#include "models.h"

CASPP_NS_BEGIN

class Sign {
#warning NYI Sign
public:
    enum Values{
        kUndefined = 0,
        kNegative=1,
        kNull=2,
        kPositive=3,
        kUnknown = 4
    };
    Sign(const Values v);

    Values value() const;
private:
    Values value_m;
};

class Comparison {
public:
    enum Values {
        kUndefined = 0,
        kAscending=1,
        kSame=2,
        kDifferent=3,
        kDescending=4,
        kUnknown = 5
    };
    Comparison(const Values v);

    bool isSame() const;
    bool isDifferent() const;
    bool isAscending() const;
    bool isDescending() const;
    bool isUnknown() const;
    bool isUndefined() const;

    bool isAscendingOrEqual() const;
    bool isDescendingOrEqual() const;

    bool operator ==(const Comparison & rhs) const;
    bool operator !=(const Comparison & rhs) const;

    Comparison symmetrize() const;

    const std::string description() const;

    Values value() const;

private:
    Values value_m;
};

class Node;

Comparison compare(const Node & lhs, const Node & rhs);

const Boolean operator <  (const Node & lhs, const Node & rhs);
const Boolean operator >  (const Node & lhs, const Node & rhs);
const Boolean operator <= (const Node & lhs, const Node & rhs);
const Boolean operator >= (const Node & lhs, const Node & rhs);
const Boolean operator == (const Node & lhs, const Node & rhs);
const Boolean operator != (const Node & lhs, const Node & rhs);

const Boolean operator <  (const NodeRef & lhs, const NodeRef & rhs);
const Boolean operator >  (const NodeRef & lhs, const NodeRef & rhs);
const Boolean operator <= (const NodeRef & lhs, const NodeRef & rhs);
const Boolean operator >= (const NodeRef & lhs, const NodeRef & rhs);
const Boolean operator == (const NodeRef & lhs, const NodeRef & rhs);
const Boolean operator != (const NodeRef & lhs, const NodeRef & rhs);

#ifdef CASPP__DO
#   error This macro should not be defined
#endif
#define CASPP__DO(__S,__T) \
    const Comparison compare(const __S & lhs,  const __T & rhs);
#ifdef CASPP_DO
#   error This macro should not be defined
#endif
#define CASPP_DO(_S) \
    CASPP__DO(_S,Boolean); \
    CASPP__DO(_S,String); \
    CASPP__DO(_S,List); \
    CASPP__DO(_S,Vector); \
    CASPP__DO(_S,Set); \
    CASPP__DO(_S,Map); \
    CASPP__DO(_S,Integer); \
    CASPP__DO(_S,Rational); \
    CASPP__DO(_S,Real); \
    CASPP__DO(_S,Symbol); \
    CASPP__DO(_S,Variable); \
    CASPP__DO(_S,Function)
CASPP_DO(Boolean);
CASPP_DO(String);
CASPP_DO(List);
CASPP_DO(Vector);
CASPP_DO(Set);
CASPP_DO(Map);
CASPP_DO(Integer);
CASPP_DO(Rational);
CASPP_DO(Real);
CASPP_DO(Symbol);
CASPP_DO(Variable);
CASPP_DO(Function);

#undef CASPP__DO
#define CASPP__DO(__S,__T) \
    const Boolean operator <  (const __S & lhs,  const __T & rhs);\
    const Boolean operator >  (const __S & lhs,  const __T & rhs);\
    const Boolean operator <= (const __S & lhs,  const __T & rhs);\
    const Boolean operator >= (const __S & lhs,  const __T & rhs);\
    const Boolean operator == (const __S & lhs,  const __T & rhs);\
    const Boolean operator != (const __S & lhs,  const __T & rhs);

CASPP_DO(Boolean);
//CASPP_DO(String);
CASPP_DO(List);
CASPP_DO(Vector);
CASPP_DO(Set);
CASPP_DO(Map);
CASPP_DO(Integer);
CASPP_DO(Rational);
CASPP_DO(Real);
CASPP_DO(Symbol);
CASPP_DO(Variable);
CASPP_DO(Function);

#undef CASPP_DO
#undef CASPP__DO

template <typename RefType>
const Comparison compare(const RefType& lhs, const RefType&rhs) {
    return compare(*lhs,*rhs);
}

CASPP_NS_END

#endif // CASPP_COMPARE_H
